package nachos.network;

import nachos.machine.*;
import nachos.threads.*;
import nachos.userprog.*;
import nachos.vm.*;
import nachos.network.*;

/**
 * A kernel with network support.
 */
public class NetKernel extends UserKernel {
    /**
     * Allocate a new networking kernel.
     */
    public NetKernel() {
	super();
    }

    /**
     * Initialize this kernel.
     */
    public void initialize(String[] args) {
	super.initialize(args);
	testing = new NetProcess();
	testing2 = new NetProcess();
	//postOffice = new PostOffice();
	postOffice = new TransportOffice();
    }

    /**
     * Test the network. Create a server thread that listens for pings on port
     * 1 and sends replies. Then ping one or two hosts. Note that this test
     * assumes that the network is reliable (i.e. that the network's
     * reliability is 1.0).
     */
    
   void connection1(){
	   testing.connect(0, 0);
	   testing.accept(0);
    }
   void connection2(){
	   testing2.connect(1, 1);

	   testing2.accept(0);
   }
   public void selfTest() {
	super.selfTest();
	KThread serverThread = new KThread(new Runnable(){
		public void run(){connection1();}
	});
	serverThread.fork();
	System.out.println(Machine.networkLink().getLinkAddress());
	KThread clientThread = new KThread(new Runnable(){
		public void run(){connection2();}
	});
	clientThread.fork();

	/*(KThread serverThread = new KThread(new Runnable() {
		public void run() { pingServer(); }
	    });

	serverThread.fork();
*/
	System.out.println("creating a transport office");
	System.out.println("Press any key to start the network test...");
	console.readByte(true);
/*
	int local = Machine.networkLink().getLinkAddress();

	// ping this machine first
	ping(local);

	// if we're 0 or 1, ping the opposite
	if (local <= 1)
	    ping(1-local);
  */
    }

    private void ping(int dstLink) {
	int srcLink = Machine.networkLink().getLinkAddress();
	
	System.out.println("PING " + dstLink + " from " + srcLink);

	long startTime = Machine.timer().getTime();
	testing.connect(dstLink, 1);
	testing.accept(0);
/*	EnhancedPacket ping;

	try {
	    ping = new EnhancedPacket(dstLink, 1,
				   Machine.networkLink().getLinkAddress(), 0, false, false, true, false, 0,
				   new byte[0]);
	}
	catch (MalformedPacketException e) {
	    Lib.assertNotReached();
	    return;
	}
*/
	//postOffice.send(ping);

	//EnhancedPacket ack = postOffice.receive(0);
	
	long endTime = Machine.timer().getTime();

	System.out.println("time=" + (endTime-startTime) + " ticks");	
    }

    private void pingServer() {

	while (true) {
		EnhancedPacket ping = postOffice.receive(1,Machine.networkLink().getLinkAddress(),0);
		testing2.connect(Machine.networkLink().getLinkAddress(), 0);
		testing2.accept(1);
		/*
		EnhancedPacket ack;

	    try {
		ack = new EnhancedPacket(ping.packet.srcLink, ping.srcPort,
				      ping.packet.dstLink, ping.dstPort, false,false,true,false,0,
				      ping.contents);
	    }
	    catch (MalformedPacketException e) {
		// should never happen...
		continue;
	    }
	    System.out.println("PINGGGG");
	    postOffice.send(ack);*/
	}	
    }
    
    /**
     * Start running user programs.
     */
    public void run() {
	super.run();
    }
    
    /**
     * Terminate this kernel. Never returns.
     */
    public void terminate() {
	super.terminate();
    }

    public static TransportOffice getTransport(){
    	return postOffice;
    }
    NetProcess testing;
    NetProcess testing2;
    static Alarm alarm;
    public static int test = 0;
    private static TransportOffice postOffice;
   // public static TransportOffice transporter;
  //  private PostOffice postOffice;
   // private TransportOffice TransportOffice;

    // dummy variables to make javac smarter
    private static NetProcess dummy1 = null;
}
